package com.zhuoyue;

import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 *
 * 用于缓存未发送成功的数据
 *
 *
 * 最大长度通过{@link ClientConfig}的 MAX_CACHE_NUM 字段获取里面拿取
 *
 *
 * @author Created by mr.liang
 */
public class CacheTimeTaskList {

    private final ClientConfig clientConfig;

    private ConnectionManagement connectionManagement;


    /** 定时器*/
    private final Timer timer;

    /** 缓存等待刷新的队列 */
    private List<TimerTask> cacheTasks =new LinkedList<>();


    public CacheTimeTaskList(ClientConfig clientConfig,ConnectionManagement connectionManagement, Timer timer){
        this.clientConfig = clientConfig;
        this.timer = timer;
        this.connectionManagement = connectionManagement;
    }

    /**
     * 将缓存全部push到timer
     */
    void sendCache(){
        synchronized(cacheTasks){
            if(cacheTasks.size() == 0){
                return ;
            }
            for (TimerTask task : cacheTasks) {
                schedule(task);
            }
            cacheTasks.clear();
        }
    }

    /**
     * 添加缓存
     */
    void addCache(TimerTask task){
        if(connectionManagement.isConnecting()){
            synchronized (cacheTasks){
                if(clientConfig.getMaxCacheNum()<=0)
                    cacheTasks.add(task);
                else{
                    if(cacheTasks.size()>clientConfig.getMaxCacheNum()){//防止队列无限大
                        cacheTasks.remove(0);
                    }
                    cacheTasks.add(task);
                }
            }
            //确认refresh结束后，能够将cache内元素send
            if(!connectionManagement.isConnecting()){
                sendCache();
            }
        }else{
            schedule(task);
        }
    }

    public int getSize() {
        return cacheTasks.size();
    }

    /** 添加任务到队列 */
    private void schedule(TimerTask task){
        resetTaskState(task);
        timer.schedule(task,0);
    }


    Field stateField = null;
    {
        try {
            stateField = TimerTask.class.getDeclaredField("state");
            stateField.setAccessible(true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    /**
     * 由于timer定时器内置状态字段，导致难以重复使用对象。
     */
    private void resetTaskState(TimerTask task) {
        try {
            stateField.set(task, 0);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

}
